/*
 * Copyright (c) 2015-2018 Sfkj Science And Technology Co.,Ltd.
 * All Rights Reserved.
 * This software is the confidential and proprietary information of
 * Sfkj Science And Technology Co.,Ltd.
 * ("Confidential Information").You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sfkj.
 */
package com.sfkj.walk.query.note;

import com.google.common.collect.Lists;
import com.sfkj.walk.api.query.note.NoteAllByPredicateQuery;
import com.sfkj.walk.api.query.user.UserOneByPredicateQuery;
import com.sfkj.walk.query.user.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.axonframework.queryhandling.QueryGateway;
import org.axonframework.queryhandling.QueryHandler;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Component
public class NoteQueryService {

    private final NoteRepository noteRepository;
    private final QueryGateway queryGateway;

    @QueryHandler
    public Iterable<Note> handle(final NoteAllByPredicateQuery query) {
        List<Note> items;
        if (Objects.nonNull(query.getPageable())) {
            Page<Note> page = noteRepository.findAll(query.getPredicate(), query.getPageable());
            List<Note> dtos = page.getContent().stream().map(this::transformNote).collect(Collectors.toList());
            return new PageImpl<>(dtos, query.getPageable(), page.getTotalElements());
        }
        if (Objects.nonNull(query.getSort())) {
            items = Lists.newArrayList(noteRepository.findAll(query.getPredicate(), query.getSort()));
            return items.stream().map(this::transformNote).collect(Collectors.toList());
        }

        items = Lists.newArrayList(noteRepository.findAll(query.getPredicate()));
        return items.stream().map(this::transformNote).collect(Collectors.toList());
    }

    private Note transformNote(Note note) {
        if (Objects.isNull(note)) {
            return null;
        }

        Note dto = new Note();
        BeanUtils.copyProperties(note, dto);

        User user = queryGateway.send(UserOneByPredicateQuery.buildById(note.getCreatorId()), User.class)
                .getNow(null);
        dto.setCreator(user);

        return dto;
    }

}
